package com.videri.match.client;

import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.rpc.IsSerializable;
import com.videri.match.client.Time;
import java.io.Serializable;
import java.util.Arrays;

/**
 * This class stores in a generic format the information necessary
 * for creating a matching game.  This class attempts to store all forms
 * of matchings as well as any objects necessary for creating the 
 * visual aspect of a matching implementation.
 * 
 * @author Matt Johnson
 * @author Michael Bauer
 *
 */
public class Matching implements IsSerializable, Serializable{
	
	private static final long serialVersionUID = 3624729412101576331L;
	private String myName;
	private Time myCreationTime;
	public String[] myStrings1 = null;
	public String[] myImages1 = null;
	public String[] myStrings2 = null;
	public String[] myImages2 = null;
	public Rectangle[] myImageRegions2 = null;
	public int my1Type = -1;
	public int my2Type = -1;
	
	private String myBackgroundImage = null;
	
	public static final int String = 0;
	public static final int Image = 1;
	public static final int ImageRegion = 2;
	
	/**
	 * This will create a generic form of a matching.
	 */
	public Matching(){
		myName = new String();
		myCreationTime = new Time(0);
		myStrings1=null;
		my1Type=-1;
		myStrings2=null;
		my2Type=-1;
	}
	
	/**
	 * This will create a matching game consisting of a
	 * matching between two sets of strings.
	 * @param name The name of the matching
	 * @param items1 The first set of string items
	 * @param items2 The second set of string items
	 */
	public Matching(String name, String[] items1, String[] items2){
		myName = name;
		myCreationTime = new Time(System.currentTimeMillis());
		myStrings1=items1;
		my1Type = Matching.String;
		myStrings2=items2;
		my2Type = Matching.String;
	}
	
	/**
	 * This will create a matching game consisting of a set of
	 * strings and locations on an image.
	 * @param name The name of the matching game
	 * @param items1 The set of string items
	 * @param items2 The locations on the image corresponding to the strings
	 * @param image The image to place the strings on
	 */
	public Matching(String name, String[] items1, Rectangle[] items2, Image image){
		myName = name;
		myCreationTime = new Time(System.currentTimeMillis());
		myStrings1=items1;
		my1Type = Matching.String;
		myImageRegions2=items2;
		my2Type = Matching.ImageRegion;
		myBackgroundImage = image.getUrl();
	}
	
	/**
	 * This will create a matching game consisting of a set of
	 * strings and a set of images.
	 * @param name The name of the matching game
	 * @param items1 The set of string items
	 * @param items2 The set of images associated with the strings
	 */
	public Matching(String name, String[] items1, Image[] items2){
		myName = name;
		myCreationTime = new Time(System.currentTimeMillis());
		myStrings1=items1;
		my1Type = Matching.String;
		myImages2 = new String[items2.length];
		for(int i = 0; i < items2.length; i++)
			myImages2[i]=items2[i].getUrl();
		my2Type = Matching.Image;
	}	
	
	/**
	 * This will create a matching game consisting of a set of
	 * images and a set of strings.  This is identical to the 
	 * previous constructor except in the actual game implementation
	 * images will be dragged instead of strings.
	 * @param name The name of the matching game
	 * @param items1 The set of image items
	 * @param items2 The set of name items
	 */
	public Matching(String name, Image[] items1, String[] items2){
		myName = name;
		myCreationTime = new Time(System.currentTimeMillis());
		myImages1 = new String[items1.length];
		for(int i = 0; i < items1.length; i++)
			myImages1[i]=items1[i].getUrl();
		my1Type = Matching.Image;
		myStrings2=items2;
		my2Type = Matching.String;
	}	
	
	/**
	 * This will create a matching game consisting of two sets
	 * of images.
	 * @param name The name of the matching game
	 * @param items1 The first set of images
	 * @param items2 The second set of images
	 */
	public Matching(String name, Image[] items1, Image[] items2){
		myName = name;
		myCreationTime = new Time(System.currentTimeMillis());
		myImages1 = new String[items1.length];
		for(int i = 0; i < items1.length; i++)
			myImages1[i]=items1[i].getUrl();
		my1Type = Matching.Image;
		myImages2 = new String[items2.length];
		for(int i = 0; i < items2.length; i++)
			myImages2[i]=items2[i].getUrl();
		my2Type = Matching.Image;
	}	
	
	/**
	 * This will create a matching game consisting of one set of
	 * images being associated with a series of locations on 
	 * another image.
	 * @param name The name of the matching
	 * @param items1 The set of images
	 * @param items2 The set of location on the background image
	 * @param background The background image
	 */
	public Matching(String name, Image[] items1, Rectangle[] items2, Image background){
		myName = name;
		myCreationTime = new Time(System.currentTimeMillis());
		myImages1 = new String[items1.length];
		for(int i = 0; i < items1.length; i++)
			myImages1[i]=items1[i].getUrl();
		my1Type = Matching.Image;
		myImageRegions2=items2;
		my2Type = Matching.ImageRegion;
		myBackgroundImage = background.getUrl();
	}		
	
	/**
	 * This will return the name of the given matching
	 * @return The matching's name
	 */
	public String getName(){
		return myName;
	}
	
	/**
	 * This will return the local time at which a matching was created
	 * @return the time the matching was created
	 */
	public Time getCreationTime(){
		return myCreationTime;
	}
	
	/**
	 * This will check whether the matching has a background associated with it
	 * @return true if the matching has a background image
	 */
	public boolean hasBackground(){
		return myBackgroundImage!=null;
	}
	
	/**
	 * This will return the background image of the matching if it has one
	 * @return the background image or null if one doesn't exist
	 */
	public Image getBackground(){
		return new Image(myBackgroundImage);
	}
	
	/**
	 * This will return the rectangle that the given location resides in on the
	 * background image.  
	 * @param x The x location
	 * @param y The y location
	 * @return The rectangle that contains the location if it exists, null otherwise
	 */
	public Rectangle getImageRegion(int x, int y)
	{
		if(my2Type != Matching.ImageRegion) //This is only a valid question if we're matching to image regions.
			return null;
		for(int i = 0; i < myImageRegions2.length; i++)
			if(myImageRegions2[i].isInside(x, y))
				return myImageRegions2[i];
		return null;
	}
	
	public boolean isMatch(String s, Rectangle r) {
		int index = -1;
		for(int i=0; i<myStrings1.length; i++) {
			if(myStrings1[i].equals(s)) index = i;
		}
		if(index==-1) return false;
		return myImageRegions2[index].equals(r);
	}

	public boolean isMatch(String s1, String s2) {
		int index = -1;
		for(int i=0; i<myStrings1.length; i++) {
			if(myStrings1[i].equals(s1)) index = i;
		}
		if(index==-1) return false;
		return myStrings2[index].equals(s2);
	}
	
	public boolean isMatch(String s, Image image) {
		int index = -1;
		for(int i=0; i<myStrings1.length; i++) {
			if(myStrings1[i].equals(s)) index = i;
		}
		if(index==-1) return false;
		return myImages2[index].equals(image.getUrl());
	}
	
}